package com.xjrh.traintravel.collector.runner;

import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 客户端连接管理类
 *
 * @author snps
 * @create 2022-01-24 9:18
 * @describe
 **/
@Component
@Order(value = 1)
@Slf4j
public class NettyClientManager implements CommandLineRunner {

    /**
     * 存储客户端连接的集合
     */
    private Map<String, Channel> mapClientChannel;

    /**
     * 存储客户端连接-最新响应时间
     */
    private Map<String, Date> mapClientChannelTime;

    /**
     * 存储：客户端连接-车序号，对应关系
     */
    private Map<String, Integer> mapClientChannelSeq;


    @Override
    public void run(String... args) throws Exception {
        log.warn("****************************************");
        mapClientChannel = new ConcurrentHashMap<>(256);
        log.warn("init ClientChannelMap...success");

        mapClientChannelTime = new ConcurrentHashMap<>(mapClientChannel.size());
        log.warn("init ClientChannelTimeMap...success");

        mapClientChannelSeq = new ConcurrentHashMap<>(mapClientChannel.size());
        log.warn("init ClientChannelSeqMap...success");
        log.warn("****************************************");
    }


    /**
     * 获取客户端连接集合
     * @return Map<String, Channel>
     */
    public Map<String, Channel> getClientChannelMap() {
        return mapClientChannel;
    }

    /**
     * 保存 客户端连接
     * @param clientChannelId 客户端连接标识（设备ID）
     * @param clientChannel 客户端连接
     */
    public void saveClientChannel(String clientChannelId, Channel clientChannel) {
        mapClientChannel.put(clientChannelId, clientChannel);
        log.info("Add Client [channelId: {}, remoteAddress: {}]", clientChannelId, clientChannel.remoteAddress());
        log.info("ClientChannel size: {}", mapClientChannel.size());
    }

    /**
     * 获取 客户端连接
     * @param clientChannelId 客户端连接标识（设备ID）
     * @return 客户端连接
     */
    public Channel getClientChannel(String clientChannelId) {
        return mapClientChannel.get(clientChannelId);
    }

    /**
     * 删除 客户端连接
     * @param clientChannelId 客户端连接标识（设备ID）
     */
    public void removeClientChannel(String clientChannelId) {
        mapClientChannel.remove(clientChannelId);
        log.info("Remove Client [channelId: {}]", clientChannelId);
        log.info("ClientChannel size: {}", mapClientChannel.size());

        if(mapClientChannelTime.containsKey(clientChannelId)) {
            mapClientChannelTime.remove(clientChannelId);
        }
        log.info("ClientChannelTime size: {}", mapClientChannelTime.size());
    }


    /***********************************************************************
     * 获取 客户端连接-最新响应时间 集合
     * @return Map<String, Channel>
     */
    public Map<String, Date> getClientChannelTimeMap() {
        return mapClientChannelTime;
    }

    /**
     * 保存 客户端连接-最新响应时间
     * @param clientChannelId
     * @param datetime
     */
    public void saveClientChannelTime(String clientChannelId, Date datetime) {
        mapClientChannelTime.put(clientChannelId, datetime);
    }

    /**
     * 获取 客户端连接-最新响应时间
     * @param clientChannelId 客户端连接标识（设备ID）
     * @return 最新响应时间
     */
    public Date getClientChannelTime(String clientChannelId) {
        return mapClientChannelTime.get(clientChannelId);
    }


    /******************************************************
     * 保存：客户端连接-车序号，对应关系
     * @param clientChannelId 客户端连接标识（设备ID）
     * @param carriageSeq 车序号
     */
    public void saveClientChannelSeq(String clientChannelId, int carriageSeq) {
        mapClientChannelSeq.put(clientChannelId, carriageSeq);
        log.info("Add Client-Seq [channelId: {}, seq: {}]", clientChannelId, carriageSeq);
    }

    /**
     * 获取：客户端连接-车序号
     * @param clientChannelId 客户端连接标识（设备ID）
     * @return 车序号
     */
    public Integer getClientChannelSeq(String clientChannelId) {
        return mapClientChannelSeq.get(clientChannelId);
    }

}